/**
 *
 */
package org.wltea.analyzer.seg;

import org.wltea.analyzer.Context;
import org.wltea.analyzer.Lexeme;
import org.wltea.analyzer.help.CharacterHelper;

/**
 * 负责处理字母的子分词器，涵盖一下范围
 * 1.英文单词、英文加阿拉伯数字、专有名词（公司名）
 * 2.IP地址、Email、URL
 *
 * @author 林良益
 */
public class LetterSegmenter implements ISegmenter {

    //链接符号
    public static final char[] Sign_Connector = new char[]{'-', '_', '.', '@', '&'};
    /*
     * 词元的开始位置，
     * 同时作为子分词器状态标识
     * 当start > -1 时，标识当前的分词器正在处理字符
     */
    private int start;
    /*
     * 记录词元结束位置
     * end记录的是在词元中最后一个出现的Letter但非Sign_Connector的字符的位置
     */
    private int end;

    /*
     * 字母起始位置
     */
    private int letterStart;

    /*
     * 字母结束位置
     */
    private int letterEnd;

    /*
     * 阿拉伯数字起始位置
     */
    private int numberStart;

    /*
     * 阿拉伯数字结束位置
     */
    private int numberEnd;


    public LetterSegmenter() {
        start = -1;
        end = -1;
        letterStart = -1;
        letterEnd = -1;
        numberStart = -1;
        numberEnd = -1;
    }

    /* (non-Javadoc)
     * @see org.wltea.analyzer.ISegmenter#nextLexeme(org.wltea.analyzer.IKSegmentation.Context)
     */
    public void nextLexeme(char[] segmentBuff, Context context) {

        //读取当前位置的char
        char input = segmentBuff[context.getCursor()];

        boolean bufferLockFlag = false;
        //处理混合字母
        bufferLockFlag = this.processMixLetter(input, context) || bufferLockFlag;
        //处理英文字母
        bufferLockFlag = this.processEnglishLetter(input, context) || bufferLockFlag;
        //处理阿拉伯字母
        bufferLockFlag = this.processPureArabic(input, context) || bufferLockFlag;

        //判断是否锁定缓冲区
        if (bufferLockFlag) {
            //对缓冲区解锁
            context.unlockBuffer(this);
        } else {
            context.lockBuffer(this);
        }
    }

    /**
     * 处理数字字母混合输出
     * 如：windos2000 | linliangyi2005@gmail.com
     *
     * @param input
     * @param context
     * @return
     */
    private boolean processMixLetter(char input, Context context) {
        boolean needLock = false;

        if (start == -1) {//当前的分词器尚未开始处理字符
            if (isAcceptedCharStart(input)) {
                //记录起始指针的位置,标明分词器进入处理状态
                start = context.getCursor();
                end = start;
            }

        } else {//当前的分词器正在处理字符
            if (isAcceptedChar(input)) {
                //输入不是连接符
                if (!isLetterConnector(input)) {
                    //记录下可能的结束位置，如果是连接符结尾，则忽略
                    end = context.getCursor();
                }

            } else {
                //生成已切分的词元
                Lexeme newLexeme = new Lexeme(context.getBuffOffset(), start, end - start + 1, Lexeme.TYPE_LETTER);
                context.addLexeme(newLexeme);
                //设置当前分词器状态为“待处理”
                start = -1;
                end = -1;
            }
        }

        //context.getCursor() == context.getAvailable() - 1读取缓冲区最后一个字符，直接输出
        if (context.getCursor() == context.getAvailable() - 1) {
            if (start != -1 && end != -1) {
                //生成已切分的词元
                Lexeme newLexeme = new Lexeme(context.getBuffOffset(), start, end - start + 1, Lexeme.TYPE_LETTER);
                context.addLexeme(newLexeme);
            }
            //设置当前分词器状态为“待处理”
            start = -1;
            end = -1;
        }

        //判断是否锁定缓冲区
        if (start == -1 && end == -1) {
            //对缓冲区解锁
            needLock = false;
        } else {
            needLock = true;
        }
        return needLock;
    }

    /**
     * 处理纯阿拉伯字符输出
     *
     * @param input
     * @param context
     * @return
     */
    private boolean processPureArabic(char input, Context context) {
        boolean needLock = false;

        if (numberStart == -1) {//当前的分词器尚未开始处理数字字符
            if (CharacterHelper.isArabicNumber(input)) {
                //记录起始指针的位置,标明分词器进入处理状态
                numberStart = context.getCursor();
                numberEnd = numberStart;
            }
        } else {//当前的分词器正在处理数字字符
            if (CharacterHelper.isArabicNumber(input)) {
                //记录当前指针位置为结束位置
                numberEnd = context.getCursor();
            } else {
                //生成已切分的词元
                Lexeme newLexeme = new Lexeme(context.getBuffOffset(), numberStart, numberEnd - numberStart + 1, Lexeme.TYPE_LETTER);
                context.addLexeme(newLexeme);
                //设置当前分词器状态为“待处理”
                numberStart = -1;
                numberEnd = -1;
            }
        }

        //context.getCursor() == context.getAvailable() - 1读取缓冲区最后一个字符，直接输出
        if (context.getCursor() == context.getAvailable() - 1) {
            if (numberStart != -1 && numberEnd != -1) {
                //生成已切分的词元
                Lexeme newLexeme = new Lexeme(context.getBuffOffset(), numberStart, numberEnd - numberStart + 1, Lexeme.TYPE_LETTER);
                context.addLexeme(newLexeme);
            }
            //设置当前分词器状态为“待处理”
            numberStart = -1;
            numberEnd = -1;
        }

        //判断是否锁定缓冲区
        if (numberStart == -1 && numberEnd == -1) {
            //对缓冲区解锁
            needLock = false;
        } else {
            needLock = true;
        }
        return needLock;
    }

    /**
     * 处理纯英文字母输出
     *
     * @param input
     * @param context
     * @return
     */
    private boolean processEnglishLetter(char input, Context context) {
        boolean needLock = false;

        if (letterStart == -1) {//当前的分词器尚未开始处理数字字符
            if (CharacterHelper.isEnglishLetter(input)) {
                //记录起始指针的位置,标明分词器进入处理状态
                letterStart = context.getCursor();
                letterEnd = letterStart;
            }
        } else {//当前的分词器正在处理数字字符
            if (CharacterHelper.isEnglishLetter(input)) {
                //记录当前指针位置为结束位置
                letterEnd = context.getCursor();
            } else {
                //生成已切分的词元
                Lexeme newLexeme = new Lexeme(context.getBuffOffset(), letterStart, letterEnd - letterStart + 1, Lexeme.TYPE_LETTER);
                context.addLexeme(newLexeme);
                //设置当前分词器状态为“待处理”
                letterStart = -1;
                letterEnd = -1;
            }
        }

        //context.getCursor() == context.getAvailable() - 1读取缓冲区最后一个字符，直接输出
        if (context.getCursor() == context.getAvailable() - 1) {
            if (letterStart != -1 && letterEnd != -1) {
                //生成已切分的词元
                Lexeme newLexeme = new Lexeme(context.getBuffOffset(), letterStart, letterEnd - letterStart + 1, Lexeme.TYPE_LETTER);
                context.addLexeme(newLexeme);
            }
            //设置当前分词器状态为“待处理”
            letterStart = -1;
            letterEnd = -1;
        }

        //判断是否锁定缓冲区
        if (letterStart == -1 && letterEnd == -1) {
            //对缓冲区解锁
            needLock = false;
        } else {
            needLock = true;
        }
        return needLock;
    }

    /**
     * @param input
     * @return
     */
    private boolean isLetterConnector(char input) {
        for (char c : Sign_Connector) {
            if (c == input) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断char是否是可接受的起始子符
     *
     * @return
     */
    private boolean isAcceptedCharStart(char input) {
        return CharacterHelper.isEnglishLetter(input)
                || CharacterHelper.isArabicNumber(input);
    }

    /**
     * 判断char是否是可接受的字符
     *
     * @return
     */
    private boolean isAcceptedChar(char input) {
        return isLetterConnector(input)
                || CharacterHelper.isEnglishLetter(input)
                || CharacterHelper.isArabicNumber(input);
    }

    public void reset() {
        start = -1;
        end = -1;
        letterStart = -1;
        letterEnd = -1;
        numberStart = -1;
        numberEnd = -1;
    }


}
